package com.tinem.platform.web.gateway.filter;

import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import com.tinem.platform.module.pojo.vo.error.UserException;
import com.tinem.platform.module.starter.jpa.entity.config.ConfigWebGatewayCountryBlacklist;
import com.tinem.platform.module.starter.jpa.repository.config.ConfigWebGatewayCountryBlacklistRepository;
import com.tinem.platform.module.starter.sdk.MessageCode;
import com.tinem.platform.web.gateway.util.GatewayUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 禁止国家访问部分服务接口。
 */
@Slf4j
@Component
public class CountryBlacklistGatewayFilterFactory extends AbstractGatewayFilterFactory<Object> implements ApplicationRunner {


    @Resource
    ConfigWebGatewayCountryBlacklistRepository configWebGatewayCountryBlacklistRepository;
    Map<String,List<ConfigWebGatewayCountryBlacklist>> country = new HashMap<>();

    AntPathMatcher antPathMatcher = new AntPathMatcher();

    @Override
    public GatewayFilter apply(Object config) {
        return (exchange, chain) ->{

            String country = StrUtil.emptyToDefault(exchange.getRequest().getHeaders().getFirst("Cf-Ipcountry"),"");
            log.debug("country:{}",country);
            // 如果未获取到国家则放行
            if(StrUtil.isEmpty(country)){
                return chain.filter(exchange);
            }
            // 如果国家不在黑名单中，则放行
            List<ConfigWebGatewayCountryBlacklist> configWebGatewayCountryBlacklists = this.country.get(country);
            if(configWebGatewayCountryBlacklists == null){
                return chain.filter(exchange);
            }
            String service = GatewayUtil.getApiService(exchange);
            String method = GatewayUtil.getApiMethod(exchange);
            // 数据库规则匹配
            Optional<ConfigWebGatewayCountryBlacklist> optional = configWebGatewayCountryBlacklists.stream()
                    .filter(countryBlacklist -> ReUtil.isMatch(countryBlacklist.getService(),service))
                    .filter(countryBlacklist -> antPathMatcher.match(countryBlacklist.getMethod(),method))
                    .findFirst();
            // 如果不在黑名单
            if(!optional.isPresent()){
                return chain.filter(exchange);
            }
            log.debug("ConfigWebGatewayCountryBlacklist id:{}",optional.get().getId());
            // 如果方法在黑名单则放行
            throw new UserException(MessageCode.ERROR_COUNTRY_BLACK_LIST);
        };
    }

    @Scheduled(cron = "0 */5 * * * ?")
    public void refresh(){
        country = configWebGatewayCountryBlacklistRepository.findAll().stream().collect(Collectors.groupingBy(ConfigWebGatewayCountryBlacklist::getCountry));
    }
    @Override
    public void run(ApplicationArguments args) throws Exception {
        refresh();
    }
}
